import customUtils from "@/custom/utils";
import customConfig from "@/custom/config";
import { ThemeColorType, BtnName, CommonObj } from "@/types";
import { toCamelCase, typeOf } from "flc-base-utils";
import _ from "lodash";
import { propsJoinChar } from "@/consts";

const { upperFirst, snakeCase, cloneDeep } = _;

const { showMessage } = customUtils;
const { cssVars, defaultFormItemTplsMap } = customConfig;

/**
 * 处理分组（操作）按钮（表格中操作列的按钮）
 * @param {object} map 事件方法映射
 * @param {string} name 触发的按钮名称
 */
export function handleBtnNext(map: CommonObj, name: BtnName) {
  map[name] ? map[name]() : showMessage(`点击了${name}按钮`, "info");
}

/**
 * 获取系统主题色
 * @param type 主题色类型
 * @returns {string}
 */
export function getSysThemeColor(type?: ThemeColorType) {
  if (!type) return;
  return cssVars["color" + upperFirst(type)];
}

/**
 * 获取获取标准的模块数据信息（处理表单项和表格列的模板）
 * @param {string} tpl 模板名称
 * @param {object} tplMap 模板映射
 * @returns {object}
 */
export function getStandardTplInfo(
  tpl: any,
  tplMap = defaultFormItemTplsMap.common
) {
  let tplInfo = tplMap[tpl];
  if (!tplInfo) throw new Error(`不存在该模板：${tpl}`);
  tplInfo = cloneDeep(tplInfo);
  if (!tplInfo.prop) tplInfo.prop = snakeCase(tpl.slice(2));
  tplInfo.tpl = tpl;
  return tplInfo;
}

/**
 * 根据路由信息生成组件名称
 * @param {object} route  路由信息
 * @returns {string} name  组件名称
 */
export function getCompNameByRoute(route: CommonObj): string {
  const { path, meta, query, matched } = route;
  const { tagIdKey = "id" } = meta;
  const defName = matched.at(-1)?.components?.default.name;
  let compName = defName ?? toCamelCase(path, true);
  if (query[tagIdKey]) compName += "Of" + query[tagIdKey];
  return compName;
}

/**
 * 判断是否位于 dialog 弹窗中
 * @param {string} selectorClassName 选择器类名
 * @param {number} maxLevel 最多监测嵌套5层
 * @param {any} baseCrudRef 目标元素DOM
 * @notice 先不要删除，后面可能会有用
 * @example 使用示例 judgeIsInDialog("basic-dialog");
 */
export function judgeIsInDialog(
  selectorClassName: string = "basic-dialog",
  maxLevel: number = 5,
  baseCrudRef: any
) {
  let isInDialog = false;
  getTargetPar(maxLevel);
  function getTargetPar(sLevel = 0) {
    let targetPar = baseCrudRef.value.parentNode;
    while (sLevel > 0) {
      targetPar = targetPar?.parentNode;
      sLevel--;
      if (targetPar?.classList?.contains(selectorClassName)) {
        isInDialog = true;
        break;
      }
    }
  }
  return isInDialog;
}

/**
 * 获取输入框的限制范围内的值
 * @param {Event} e 事件对象
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @returns
 */
export const getInputLimitNum = (
  value: any,
  min?: number,
  max?: number,
  fixNum?: number
) => {
  if ([null, undefined, ""].includes(value)) return value;
  let val: string | number = Number(value);
  if (min !== undefined && val < min) val = min;
  if (max !== undefined && val > max) val = max;
  if (fixNum !== undefined) val = val.toFixed(2);
  return val;
};

/**
 * 将联合prop拆成两个字段（不会修改原对象）
 * @param {object} obj 要拆解的对象
 * @param {boolean} isRange 是否是区间数组
 * @returns {object} args
 */
export function splitPropsParams(args: CommonObj): CommonObj {
  const obj = JSON.parse(JSON.stringify(args));
  const entrs = Object.keys(obj).filter((it) => it.includes(propsJoinChar));
  entrs.forEach((prop: string) => {
    if (!obj[prop]) return;
    const t = typeOf(obj[prop]);
    //区间数组 [min,max] = [最小值，最大值]
    if (t === "Array") {
      const [minProp, maxProp] = prop.split(propsJoinChar);
      const [minVal, maxVal] = obj[prop];
      obj[minProp] = minVal;
      obj[maxProp] = maxVal;
    } else if (t === "Object") {
      //表单字段中无prop，但是有children属性
      const keys = prop.split(propsJoinChar);
      keys.forEach((key: string) => {
        obj[key] = obj[prop][key];
      });
    } else {
      throw new Error(`暂未处理此类型：${t}`);
    }
    delete obj[prop];
  });
  return obj;
}
